// @Author EthanScriptOn
// @Desc
package queue

import (
	"time"
)

// QueueLoadMonitor Queue monitor
type QueueLoadMonitor struct {
	workerQueue Queue     // workerQueue Work queues
	startTime   time.Time // startTime The time when the listening began
}

func GenerateQueueLoadMonitor(workerQueue Queue) *QueueLoadMonitor {
	return &QueueLoadMonitor{
		workerQueue: workerQueue,
		startTime:   time.Now(),
	}
}

// GetCurrentQueueLength Gets the length of the current queue
func (q *QueueLoadMonitor) GetCurrentQueueLength() int {
	return q.workerQueue.QueueLen()
}

// GetQueueCap Gets the capacity of the current queue
func (q *QueueLoadMonitor) GetQueueCap() int {
	return q.workerQueue.QueueCap()
}

// GetAverageQueueLength Gets the throughput of the current queue
func (q *QueueLoadMonitor) GetAverageQueueLength() float64 {
	totalTasks := q.workerQueue.TasksTotal()
	if totalTasks == 0 {
		return 0
	}
	return float64(q.workerQueue.ProcessedTasks()) / float64(totalTasks)
}

// GetThroughput Get the efficiency of the current queue
func (q *QueueLoadMonitor) GetThroughput() float64 {
	duration := time.Since(q.startTime).Seconds()
	if duration == 0 {
		return 0
	}
	return float64(q.workerQueue.ProcessedTasks()) / duration
}

// GetLoadPercentage Get a comprehensive metric of a queue's processing power
func (q *QueueLoadMonitor) GetLoadPercentage() float64 {
	currentQueueLength := q.GetCurrentQueueLength()
	averageQueueLength := q.GetAverageQueueLength()
	throughput := q.GetThroughput()

	loadScore := 0.4*float64(currentQueueLength)/float64(q.GetQueueCap()) +
		0.3*averageQueueLength +
		0.3*(1/throughput)
	return loadScore * 100
}
